package test.envset;

import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Enumeration;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import java.util.Properties;

/*
 * @ 2022-10-17
 *运行环境变量信息
 */
public class RunEnv {
    //metadata
    public static String JDBC_DRIVER = "dm.jdbc.driver.DmDrivr";
    public static String META_URL = "jdbc:dm://localhost:5236";
    public static String META_USR = "SYSDBA";
    public static String META_PWD = "SYSDBA";
    public static String META_SCHEMAS = "SYSDBA";
    public static SimpleDateFormat dateFormatLog = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //默认时间格式

    public static SimpleDateFormat sqlDateFormat = new SimpleDateFormat("yyyyMMddHHmm"); //默认时间格式
    //LEVEL
//sql的复杂度,可以为easy, medium, hard, extrahard.
//默认值为hard
// 可以设置多个，用|分隔
    public static String LEVEL = "hard";
    //COUNT
// 生成sql的总数。如果设置为0，那么就是无限制
// 默认值为10000
    public static int COUNT = 10000;
    //SAVE
// 是否保存生成的sql。即使设置为不保存，也会保留最近的100条SQL
//0:不保存; 1:保存所有sql; 2:仅保留执行成功的sql
// 默认值为1
    public static int SAVE = 1;
    //EXECUTE
// 是否执行sql。
// 默认值为1
    public static int EXECUTE = 1;
    //WORKERS
//工作线程数，默认为1
    public static int WORKERS = 1;

    //MAX_WIDTH
//SQL的最大宽度,默认为2000
    public static int MAX_WIDTH = 2000;
    //MAX_DEPTH
//SQL的最大深度,默认为10
    public static int MAX_DEPTH = 10;

    //    int test.envset.RunEnv.MAX_DEPTH
//含有一个层次子查询估算时
    public static int MIN_WIDT_COMP = 50;
    //最小的复合表达式宽度，默认
    public static int MAX_EXP_WIDT = 10;
    //查询谓词控制
    public static boolean NULL_FlAG = true;
    public static boolean LIKE_FLAG = true;

    public static boolean IN_FLAG = true;
    public static boolean BETWEEN_FLAG = true;
    public static boolean EXISTS_FLAG = true;

    public static boolean LOGIC_ALL_FLAG = true;

    public static boolean CASE_FLAG = true;

    public static boolean SUBSELECT_FLAG = true;
    //with语句数量限制
    public static int MAX_WITH_CTES = 3;

    public static int MAX_UNION_OPERATORS=3;
    //case when语句数量限制
    public static int MAX_CASE_WHEN=10;

    //    加载驱动
    private static void loadDriver() {
        try {
            Class.forName(JDBC_DRIVER);
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
            System.exit(1);
        }
    }

    //需要额外设置处理的属性集
//例如，有些关联性属性，需要最后进行处理
    private static void lastSetProperties(Properties pros) {
//todo
        checkParas();
//加载驱动
        loadDriver();
    }

    //参数值合法性检查
//检查参数合法性。如果不合法，那么就设置为默认值
    private static void checkParas() {
        if (COUNT < 0) {
            COUNT = 10000;
        }
        if (SAVE < 0 || SAVE > 2) {
            SAVE = 1;
        }
        if (EXECUTE < 0 || EXECUTE > 1) {
            EXECUTE = 1;
        }
//如果SQL总数未限制，那么不保存SQL
//        if (COUNT == 0) {
//            SAVE = 0;
//        }
//如果不保存，那么需要执行SQL
        if (SAVE == 0) {
            EXECUTE = 1;
        }
        if (MAX_WIDTH < 50) {
            MAX_WIDTH = 50;
        }
        if (MAX_DEPTH < 1) {
            MAX_DEPTH = 1;
        }
    }

    //设置环境属性
    private static void setProperties(Properties pros) {
        Enumeration<Object> keys = pros.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            try {
                setPropertyLow(key, pros.getProperty(key).trim());
                System.out.println("[Set]" + key + " = " + pros.getProperty(key));
            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                System.err.println("[Warning]'" + key + "' set Failed! ErrMsg:" + e.getMessage());
            }
        }
        lastSetProperties(pros);
    }

    //需要根据不同类型设置值
    @SuppressWarnings("rawtypes")
    public static void setPropertyLow(String key, String value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {

        {
            Field staProf = RunEnv.class.getDeclaredField(key);
            Class prot = staProf.getType();
            String tname = prot.getName();
            if (tname.equals("java. lang. String")) { //String 类型
                staProf.set(null, value);
            } else if (tname.equals("java. lang. Integer") || prot == Integer.TYPE) { //int类型
                staProf.set(null, Integer.valueOf(value));
            } else if (tname.equals("java. lang. Long") || prot == Long.TYPE) { //long 类型
                staProf.set(null, Long.valueOf(value));
            } else if (tname.equals("java. lang. Boolean") || prot == Boolean.TYPE) { //boolean 类型
                if (value.trim().equalsIgnoreCase("0")) {
                    staProf.set(null, false);
                } else {
                    staProf.set(null, true);
                }
            } else {
                staProf.set(null, value);
            }
        }
    }

    //读取属性文件，设置运行时环境
    public static void setRunEnv(String profile) {
        System.out.println("[profile]" + profile);
        Properties pros = new Properties();
        try {
            BufferedReader bufReader = new BufferedReader(new FileReader(profile));
            pros.load(bufReader);
            bufReader.close();
            setProperties(pros);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("read configuration error, use default RunEnv");
        }
    }

}